﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Markup;
using System.Windows.Media;
using Wpf.CommonTools.SystemExtension;

namespace Wpf.CommonTools.StaticExtension
{
    public class PopFormArg : EventArgs
    {
        public object State { get; set; }

        public PopFormArg()
        {
        }

        public PopFormArg(object state)
        {
            this.State = state;
        }
    }

    public class PopForm
    {
        Window win;
        Popup p;

        double _width = 300;
        double? _height = null;
        //private static Thread thHideAlert;
        //private static Thread thChangProcessing;
        public delegate void PopFrocessingDelegate(object sender, PopFormArg arg);

        public PopForm(Window win)
        {
            this.win = win;
            p = addPopForm(_width, _height);
        }

        public void PopAlertDialogue(string message, bool success = true, int autoCloseTime = 2000, PopFrocessingDelegate callBack = null, EventHandler cancelEvent = null)
        {
            Window alert = addDialogue(message, autoCloseTime, _width, _height, callBack, cancelEvent);
            win.Dispatcher.Invoke(() =>
            {
                TextBlock tb = (TextBlock)((Grid)alert.Content).Children[0];
                tb.Text = message;
                if (!success)
                {
                    tb.Foreground = new SolidColorBrush(Colors.Red);
                }
                alert.SetCenterOfWindow(win);
                alert.ShowDialog();
            });
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        /// <param name="processing"></param>
        /// <param name="callBack"></param>
        /// <param name="cancelEvent"></param>
        public void PopAlertDialogue(string message, PopFrocessingDelegate processing, PopFrocessingDelegate callBack = null, EventHandler cancelEvent = null)
        {
            Window alert = addDialogue(message, 0, _width, _height, null, cancelEvent);
            win.Dispatcher.Invoke(() =>
            {
                TextBlock tb = (TextBlock)((Grid)alert.Content).Children[0];
                tb.Text = message;
                alert.SetCenterOfWindow(win);
                if (processing != null)
                {
                    new Thread(new ThreadStart(() =>
                    {
                        PopFormArg arg = new PopFormArg();
                        processing(this, arg);
                        win.Dispatcher.Invoke(() =>
                        {
                            if (alert.IsLoaded)
                            {
                                try
                                {
                                    alert.DialogResult = true; alert.Close();
                                }
                                catch { }
                            }
                            if (alert.DialogResult == true && callBack != null)
                            {
                                callBack(this, arg);
                            }
                        });

                    })) { IsBackground = true }.Start();
                }
                alert.ShowDialog();
            });

        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        /// <param name="success"></param>
        /// <param name="autoCloseTime"></param>
        public void PopAlertMessage(string message, bool success = true, int autoCloseTime = 2000, EventHandler onClose = null)
        {
            double width = 500, height = 300;
            win.Dispatcher.Invoke(() =>
            {
                width = win.ActualWidth / 2;
                height = -win.ActualHeight / 2;
            });
            p.Dispatcher.Invoke(() =>
            {
                double winWidth = double.IsNaN(p.Width) ? 0 : p.Width / 2;
                double winHeight = double.IsNaN(p.Height) ? 0 : p.Height / 2;

                p.HorizontalOffset = width - winWidth;
                p.VerticalOffset = height - winHeight;   //让创建的面板始终都在textbox空间的下方
                p.IsOpen = true;

                TextBlock tb = (TextBlock)(((StackPanel)(((Border)p.Child).Child)).Children[0]);
                tb.Text = message;
                tb.Foreground = new SolidColorBrush(success ? Colors.Black : Colors.Red);
                setProcessingText(tb, message, autoCloseTime, p, onClose);
            });
        }

        public void PopAlertClose()
        {
            win.Dispatcher.Invoke(() => { p.IsOpen = false; });
        }

        private void setProcessingText(TextBlock tb, string message, int autoCloseTime, object form, EventHandler onClose = null)
        {
            if (message.EndsWith("..."))
            {
                string str = message.Substring(0, message.Length - 3);
                Thread thChangProcessing = new Thread(new ThreadStart(delegate()
                {
                    int i = 0;
                    while (true)
                    {
                        i++;
                        string fMessage = str + string.Empty.PadLeft(i % 4, '.');
                        bool isOpen = true;
                        tb.Dispatcher.Invoke(() =>
                        {
                            isOpen = Window.GetWindow(tb).IsLoaded;
                            tb.Text = fMessage;
                        });
                        if (!isOpen)
                        {
                            break;
                        }
                        Thread.Sleep(500);
                    }
                })) { IsBackground = true };
                try
                {
                    thChangProcessing.Start();
                }
                catch { }
            }

            if (autoCloseTime > 0)
            {
                Thread thHideAlert = new Thread(new ThreadStart(delegate()
                {
                    Thread.Sleep(autoCloseTime);
                    win.Dispatcher.Invoke(() =>
                    {
                        Window w = form as Window;
                        if (w != null)
                        {
                            if (w.IsLoaded) { w.DialogResult = true; w.Close(); };
                        }
                        else
                        {
                            ((Popup)form).IsOpen = false;
                        }
                        if (onClose != null)
                        {
                            onClose(w, new EventArgs());
                        }
                    });
                })) { IsBackground = true };
                try
                {
                    thHideAlert.Start();
                }
                catch { }
            }
        }

        private Popup addPopForm(double? width = 300, double? height = null)
        {
            win.Dispatcher.Invoke(() =>
            {
                var effect = new System.Windows.Media.Effects.DropShadowEffect();

                p = new Popup();
                if (width.HasValue)
                {
                    p.Width = width.Value;
                }
                if (height.HasValue)
                {
                    p.Height = height.Value;
                }
                p.AllowsTransparency = true;
                Border border = new Border();
                border.Margin = new Thickness(5);
                border.BorderBrush = new SolidColorBrush(Colors.Gray);
                border.BorderThickness = new Thickness(1);
                border.Background = new SolidColorBrush(Colors.White);

                StackPanel panel1 = new StackPanel();
                panel1.Effect = effect;
                //panel1.Margin = new Thickness(5);
                panel1.Background = new SolidColorBrush(Colors.White);

                TextBlock tb = new TextBlock();
                tb.Name = "tbPopMessage";
                tb.Text = "";
                tb.TextWrapping = TextWrapping.Wrap;
                tb.Margin = new Thickness(10);

                panel1.Children.Add(tb);
                border.Child = panel1;
                p.Child = border;

                ((Grid)win.Content).Children.Add(p);
            });
            return p;
        }

        private Window addDialogue(string message, int autoCloseTime, double width, double? height, PopFrocessingDelegate callBack, EventHandler cancelEvent)
        {
            Window alert = null;
            win.Dispatcher.Invoke(() =>
            {
                alert = new Window();
                alert.SizeToContent = SizeToContent.WidthAndHeight;
                alert.Width = width;

                if (height.HasValue)
                {
                    alert.Height = height.Value;
                }
                alert.ShowInTaskbar = false;
                alert.Topmost = true;
                alert.ResizeMode = ResizeMode.NoResize;
                Grid panel1 = new Grid();
                TextBlock tb = new TextBlock();
                tb.Text = message;
                tb.TextWrapping = TextWrapping.Wrap;
                tb.Margin = new Thickness(10);
                tb.Width = 300;
                panel1.Children.Add(tb);
                ((IAddChild)alert).AddChild(panel1);

                alert.Loaded += (object sender1, RoutedEventArgs e1) =>
                {
                    setProcessingText(tb, message, autoCloseTime, alert);
                };
                alert.Closed += (object sender2, EventArgs e2) =>
                {
                    if (alert.DialogResult == true)
                    {
                        if (callBack != null)
                        {
                            callBack(sender2, null);
                        }
                    }
                    else
                    {
                        if (cancelEvent != null)
                        {
                            cancelEvent(this, new EventArgs());
                        }
                    }
                };
            });
            return alert;
        }
    }
}
